package com.metamech.vorpal.handler;

import org.apache.log4j.Logger;

import com.metamech.jabber.Authenticator;
import com.metamech.jabber.ErrorTool;
import com.metamech.jabber.Session;
import com.metamech.jabber.xml.Packet;
import com.metamech.jabber.xml.PacketListener;
import com.metamech.log.Log;
import com.metamech.vorpal.Server;
import com.metamech.vorpal.User;
import com.metamech.vorpal.UserIndex;


public class RegisterHandler implements PacketListener {
	private static Logger logger=Logger.getLogger(RegisterHandler.class);
	static UserIndex userIndex;
	Packet required;
	Authenticator auth = new Authenticator();

	public RegisterHandler(UserIndex index) {
	    userIndex = index;
	    required = new Packet("iq");
	    required.setFrom(Server.SERVER_NAME);
	    required.setType("result");
	    new Packet("username").setParent(required);
	    new Packet("password").setParent(required);
	    new Packet("hash").setParent(required);
	}

	// 2 types of register
	//
	// set - tries to register a new user
	// get - obtains required fields
	public void notify(Packet packet){
		
		logger.info("Register handling " + packet.toString());
	    String type = packet.getType();
	    Packet query = packet.getFirstChild("query");

	    if (type.equals("get")){
	    	logger.info("Register : Get ");
	    	
	    	required.setSession(packet.getSession());
	    	required.setID(packet.getID());
	    	MessageHandler.deliverPacket(required);
	    	return;

	    } else if (type.equals("set")) { // type == set
	    	
	    	logger.info("Register : Set ");
	    	
	    	String username = query.getChildValue("username");
	    	String password = query.getChildValue("password");
	    	User user = userIndex.getUser(username);
	    	if (user != null){ // user exists
	    		if (packet.getSession().getStatus() != Session.AUTHENTICATED ||
	    			!username.equals(packet.getSession().getJID().getUser())){
	    			
	    			Packet iq = new Packet("iq");
	    			iq.setSession(packet.getSession());
	    			iq.setID(packet.getID());
	    			ErrorTool.setError(iq,401,"User account already exists");
	    			MessageHandler.deliverPacket(iq);
	    			return;
	    		}
	    	} else {
	    		user = userIndex.addUser(username, password);
	    	}
	    	user.setPassword(password);
	    	user.setHash(query.getChildValue("hash"));
	    	user.setSequence(query.getChildValue("sequence"));
	    	user.setToken(query.getChildValue("token"));
	    	if (user.getHash() == null || user.getSequence() == null || user.getToken() == null){
	    		if (user.getPassword() != null){
	    			user.setToken(Authenticator.randomToken());
	    			user.setSequence("99");
	    			user.setHash(auth.getZeroKHash(100,	user.getToken().getBytes(), user.getPassword().getBytes()));
	    		}
	    	} else {
	    		// Adjust sequence number to be ready for next request.
	    		// Book readers.  In the book this was listed earlier resulting in a thrown
	    		// exception if 0k registration was not used.  This fixes it.  :)
	    		user.setSequence(Integer.toString(Integer.parseInt(user.getSequence()) - 1));
	    	}
	    	
	    	Packet iq = new Packet("iq");
	    	iq.setSession(packet.getSession());
	    	iq.setID(packet.getID());
	    	iq.setType("result");   // success
	    	MessageHandler.deliverPacket(iq);
	    	logger.info("Register successfully registered " + username + " with password " + query.getChildValue("password"));
	   
	    } else {
	    	logger.info("Register ignoring " + packet.toString());
	    }
	}
	  
}
